package auto.app.controller;


import auto.app.controller.from.rule.RuleAddFrom;
import auto.app.controller.from.rule.RuleApiFrom;
import auto.app.controller.from.rule.RulePage;
import auto.app.controller.info.InterFacePath;
import auto.app.controller.info.ruleInfo.RuleApiInfo;
import auto.app.controller.info.ruleInfo.RuleKey;
import auto.app.dao.ResourceDao;
import auto.app.exetion.HibernateExetion;
import auto.app.exetion.MainExection;
import auto.app.model.*;
import auto.app.service.*;
import auto.app.util.CommonUtil;
import auto.app.util.Result;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.PostConstruct;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import static auto.app.exetion.MainExetionMessage.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 杨森
 * @since 2022-07-08
 */
@RestController
@RequestMapping("/rule")
@Api(value = "角色管理",tags = "角色管理")
@AllArgsConstructor
@Slf4j
public class RuleController {
    RuleService ruleService;
    AccountRuleService accountRuleService;
    RuleMenusService ruleMenusService;
    WebApplicationContext applicationContext;
    ResourceService resourceService;
    RuleResourceService ruleResourceService;
    ResourceDao resourceDao;

    @PostMapping(name = "新增角色")
    @ApiOperation(value = "新增角色",notes = "新增角色")
    public Result<Boolean> addRule(@Valid @RequestBody RuleAddFrom ruleAddFrom) throws MainExection {
        Rule rule = CommonUtil.copyOne(ruleAddFrom, Rule.class);
        rule.setCreateTime(LocalDateTime.now());
        Rule one = ruleService.getOne(new LambdaQueryWrapper<Rule>().eq(Rule::getRuleName, ruleAddFrom.getRuleName()));
        if (ObjectUtil.isNotNull(one)){
            throw new MainExection(RULENAMEEMPTY.getCode(),RULENAMEEMPTY.getMsg());
        }
        boolean save = ruleService.save(rule);
        return Result.getInstance(Boolean.class).setData(save);
    }

    @GetMapping(value = "/list",name = "角色列表")
    @ApiOperation(value = "角色列表",notes = "角色列表")
    public Result<Page> listRule( RulePage RulePage){
        LambdaQueryWrapper<Rule> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(RulePage.getRuleName()),Rule::getRuleName,RulePage.getRuleName())
                .orderByDesc(Rule::getCreateTime);
        RulePage rulePage = ruleService.page(RulePage, lambdaQueryWrapper);
        return Result.getInstance(Page.class).setData(rulePage);
    }

    @DeleteMapping(value = "/{ruleId}",name = "删除角色")
    @ApiOperation(value = "删除角色",notes = "删除角色")
    public Result<Boolean> deleteRule(@PathVariable Integer ruleId) throws MainExection {
        Rule ruleServiceById = ruleService.getById(ruleId);
        if (ObjectUtil.isNull(ruleServiceById)){
            throw new MainExection(RULENULL.getCode(),RULENULL.getMsg());
        }
        //若账号跟角色之间存在关联关系 则不能删除
        LambdaQueryWrapper<AccountRule>lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AccountRule::getRuleId,ruleId);
        List<AccountRule> list = accountRuleService.list(lambdaQueryWrapper);
        if (ObjectUtil.isNotNull(list) && list.size()>0){
            throw new MainExection(ACCOUNTRULE.getCode(),ACCOUNTRULE.getMsg());
        }
        //若无关联直接删除
        boolean b = ruleService.removeById(ruleId);
        return Result.getInstance(Boolean.class).setData(b);
    }

    @GetMapping(value = "/list/type",name = "角色类型")
    @ApiOperation(value = "角色类型",notes = "角色类型")
    public Map<String,Integer> getListType(){
        List<Rule> list = ruleService.list();
        return list.stream().collect(Collectors.toMap(Rule::getRuleName, Rule::getRuleId));
    }

    @PostMapping(value = "/rulegrantrole/{ruleId}",name = "角色关联菜单")
    @ApiOperation(value = "角色关联菜单",notes = "角色关联菜单")
    public Result<Boolean> rulegrantrole(@RequestBody List<Integer> rulemensList,@PathVariable Integer ruleId ) throws MainExection {
        //判断角色是否存在
        Rule byId = ruleService.getById(ruleId);
        if (ObjectUtil.isNull(byId)){
            throw new MainExection(RULENULL.getCode(),RULENULL.getMsg());
        }
        ArrayList<RuleMenus> arrayList=new ArrayList<>();
        for (Integer integer : rulemensList) {
            arrayList.add(RuleMenus.builder().menusId(integer).ruleId(ruleId).build());
        }
        boolean b = ruleMenusService.saveBatch(arrayList);
        return Result.getInstance(Boolean.class).setData(b);
    }

    @PostMapping(value = "/setInterface",name = "设置接口")
    @ApiOperation(value = "设置接口",notes = "设置接口")
    public Result<Boolean> setInterface(@RequestBody RuleApiFrom ruleApiFrom) throws MainExection {
        //判断角色是否存在
        Rule ruleServiceById = ruleService.getById(ruleApiFrom.getRuleId());
        if (ObjectUtil.isNull(ruleServiceById)){
            throw new MainExection(RULENULL.getCode(),RULENULL.getMsg());
        }
        //移除之前的
        List<RuleResource> list = ruleResourceService.list(new LambdaQueryWrapper<RuleResource>().eq(RuleResource::getRuleId, ruleApiFrom.getRuleId()));
        boolean b = ruleResourceService.removeByIds(list.stream().map(RuleResource::getRuleResourceId).collect(Collectors.toList()));
        //新的进行复制
        ArrayList<RuleResource> arrayList=new ArrayList<>();
        List<Integer> value = ruleApiFrom.getValue();
        value.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                RuleResource ruleResource=new RuleResource();
                ruleResource.setRuleId(ruleApiFrom.getRuleId());
                ruleResource.setResourceId(integer);
                ruleResource.setIsDeleted(0);
                arrayList.add(ruleResource);
            }
        });
        boolean b1 = ruleResourceService.saveBatch(arrayList);
        return Result.getInstance(Boolean.class).setData(b1);
    }

    @GetMapping(value = "/getInterfacePathById/{ruleId}",name ="获取指定角色的配置接口" )
    @ApiOperation(value = "获取指定角色的配置接口",notes = "获取指定角色的配置接口")
    public Result<RuleApiInfo> getInterfacePathById(@PathVariable Integer ruleId){
        //查询该角色拥有的权限
        List<Resource> resourceByRuleId = resourceDao.findResourceByRuleId(ruleId);
        List<Integer> collect = resourceByRuleId.stream().map(Resource::getResourceId).collect(Collectors.toList());
        //查询所有的接口
        List<Resource> list = resourceService.list();
        ArrayList<RuleKey> ruleKeyList=new ArrayList<>();
        list.forEach(resource -> {
            RuleKey build = RuleKey.builder().key(resource.getResourceId()).label(resource.getResourceName()).disabled(false).build();
            ruleKeyList.add(build);
        });
        RuleApiInfo ruleApiInfo=new RuleApiInfo();
        ruleApiInfo.setRuleKeyList(ruleKeyList);
        ruleApiInfo.setValue(collect);
        return Result.getInstance(RuleApiInfo.class).setData(ruleApiInfo);
    }

    @GetMapping(value = "/getInterfacePath",name = "获取所有接口")
    @ApiOperation(value = "获取所有接口",notes = "获取所有接口")
    public Result<List<InterFacePath>> getInterfacePath(){
        log.info("初始化所有接口到接口表中");
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        // 拿到Handler适配器中的全部方法
        Map<RequestMappingInfo, HandlerMethod> methodMap = mapping.getHandlerMethods();
        ArrayList<InterFacePath> arrayList=new ArrayList<>();
        for (RequestMappingInfo info : methodMap.keySet()){
            //获取请求路径
            Set<String> urlSet = info.getPatternsCondition().getPatterns();
            // 获取全部请求方式
            Set<RequestMethod> Methods = info.getMethodsCondition().getMethods();
            //获取全部请求名称
            String urlName =  info.getName();
            for (String url : urlSet){
                for (RequestMethod method : Methods) {
                    if(StrUtil.isNotBlank(urlName) && StrUtil.isNotBlank(method.toString()) ){
                        InterFacePath build = InterFacePath.builder().url(url).methods(method.toString()).name(urlName).build();
                        arrayList.add(build);
                    }
                }
            }
        }
        List<InterFacePath> collect = arrayList.stream().sorted(Comparator.comparing(InterFacePath::getUrl).reversed()).collect(Collectors.toList());
        //查询所有的接口
        Map<String, List<Resource>> stringListMap = resourceService.list().stream().collect(Collectors.groupingBy(Resource::getResourceUri));
        //对没有的进行新增
        ArrayList<Resource> arrayList1=new ArrayList<>();
        for (InterFacePath interFacePath : collect) {
            if (ObjectUtil.isNull(stringListMap.get(interFacePath.getUrl()))){
                Resource resource=new Resource();
                resource.setResourceName(interFacePath.getName());
                resource.setResourceUri(interFacePath.getUrl());
                resource.setResourceStatus(0);
                arrayList1.add(resource);
                continue;
            }else {
                continue;
            }
        }
        log.info("初始化完成");
        boolean b = resourceService.saveBatch(arrayList1);
        return Result.getInstanceList(InterFacePath.class).setData(collect);
    }

    @PostConstruct
    public void getInterfacePathAll(){
        log.info("初始化所有接口到接口表中");
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        // 拿到Handler适配器中的全部方法
        Map<RequestMappingInfo, HandlerMethod> methodMap = mapping.getHandlerMethods();
        ArrayList<InterFacePath> arrayList=new ArrayList<>();
        for (RequestMappingInfo info : methodMap.keySet()){
            //获取请求路径
            Set<String> urlSet = info.getPatternsCondition().getPatterns();
            // 获取全部请求方式
            Set<RequestMethod> Methods = info.getMethodsCondition().getMethods();
            //获取全部请求名称
            String urlName =  info.getName();
            for (String url : urlSet){
                for (RequestMethod method : Methods) {
                    if(StrUtil.isNotBlank(urlName) && StrUtil.isNotBlank(method.toString()) ){
                        InterFacePath build = InterFacePath.builder().url(url).methods(method.toString()).name(urlName).build();
                        arrayList.add(build);
                    }
                }
            }
        }
        List<InterFacePath> collect = arrayList.stream().sorted(Comparator.comparing(InterFacePath::getUrl).reversed()).collect(Collectors.toList());
        //查询所有的接口
        Map<String, List<Resource>> stringListMap = resourceService.list().stream().collect(Collectors.groupingBy(Resource::getResourceUri));
        //对没有的进行新增
        ArrayList<Resource> arrayList1=new ArrayList<>();
        for (InterFacePath interFacePath : collect) {
            if (ObjectUtil.isNull(stringListMap.get(interFacePath.getUrl()))){
                Resource resource=new Resource();
                resource.setResourceName(interFacePath.getName());
                resource.setResourceUri(interFacePath.getUrl());
                resource.setResourceStatus(0);
                arrayList1.add(resource);
                continue;
            }else {
                continue;
            }
        }
        boolean b = resourceService.saveBatch(arrayList1);
        log.info("初始化完成");
    }

}

